package com.inspur.edp.udt.designtime.manager.generatecomponent.componentgenerators;


import com.inspur.edp.bef.component.base.GspComponent;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.service.MetadataService;
import com.inspur.edp.udt.designtime.api.entity.validation.ValidationInfo;
import com.inspur.edp.udt.designtime.api.exception.UdtModelErrorCodeEnum;
import com.inspur.edp.udt.designtime.api.exception.UdtModelException;
import com.inspur.edp.udt.designtime.api.utils.UdtUtils;
import com.inspur.edp.udt.designtime.manager.generatecomponent.ComponentGenUtil;
import com.inspur.edp.udt.designtime.manager.generatecomponent.GspMetadataExchangeUtil;
import com.inspur.edp.udt.designtime.manager.generatecomponent.JavaCompCodeNames;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

/**
 * 构件元数据生成器基类
 */
public abstract class BaseComponentGenerator {

  /**
   * UDTDef编号
   */
  protected String udtDefCode;
  /**
   * UDTDef程序集名称u
   */
  protected String assemblyName;
  protected String udtAssemblyName;
  protected String nameSpace;
  /**
   * 原始构件
   */
  protected GspComponent originalComponent;
  protected String bizObjectID;

  /**
   * 生成构件元数据
   *
   * @param vldInfo 业务操作
   * @param path 生成指定路径
   * @param udtDefCode 业务实体编号
   * @param assemblyName 业务实体程序集名称
   */
  public final void GenerateComponent(ValidationInfo vldInfo, String path, String udtDefCode,
      String assemblyName, String defaultNamespace, String bizObjectID, String udtAssemblyName) {
    this.udtDefCode = udtDefCode;
    this.assemblyName = assemblyName;
    this.udtAssemblyName = udtAssemblyName;
    this.nameSpace = defaultNamespace;
    this.bizObjectID = bizObjectID;
    if (vldInfo.getCmpId() == null || "".equals(vldInfo.getCmpId())) {
      createComponent(vldInfo, path);
    } else {
      modifyComponent(vldInfo, path);
    }
  }

  /**
   * 新建构件
   */
  private void createComponent(ValidationInfo vldInfo, String path) {
    //1、构建实体
    GspComponent component = buildComponent();
    //2、赋值
    evaluateComponentInfo(component, vldInfo, null);
    //3、生成构件
    String componentMetadataName = establishComponent(component, path);
    //4、建立Action与元数据之间的关联关系
    vldInfo.setCmpId(component.getComponentID());
    //操作的ComponentName用来记录生成的构件元数据的名称
    vldInfo.setCmpName(componentMetadataName);
    vldInfo.setIsGenerateComponent(true);
  }

  /**
   * 构造构件实体类
   *
   * @return 构件实体类
   * <see cref="IGspComponent"/>
   */
  protected abstract GspComponent buildComponent();

  /**
   * 为构件赋值
   *
   * @param component 构件实体信息
   * @param vldInfo 动作信息
   */
  protected abstract void evaluateComponentInfo(GspComponent component, ValidationInfo vldInfo,
      GspComponent originalComponent);

  /**
   * 生成构件实体对应的构件元数据
   *
   * @param component 构件实体
   * @param path 生成构件元数据指定路径
   * @return 生成的构件元数据名称
   * <see cref="string"/>
   */
  private String establishComponent(GspComponent component, String path) {
    return GspMetadataExchangeUtil
        .getInstance()
        .establishGSPMetdadata(component, path, this.udtDefCode, this.bizObjectID, this.nameSpace);
  }

  /**
   * 修改构件
   */
  private void modifyComponent(ValidationInfo vldInfo, String path) {
    //1、构建实体
    GspComponent component = buildComponent();

    String fullPath = "";

    ///#region ----------- 兼容旧版本命名规则（此种情况适用于构件名称未修改）--------------
    MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);

    // 得到具体类型的构件扩展名
    String cmpExtendName = JavaCompCodeNames.UDTValCmpExtendName;
    // 带针对不同类型构件的扩展名的文件全名
    String metadataFileNameWithExtendName =
        vldInfo.getCmpName() + JavaCompCodeNames.ComponentExtensionName;

//		需要Lcm提供该接口的isMetadatExist
    if (metadataService.isMetadataExist(path, metadataFileNameWithExtendName)) {
      String oldFileNameWithExtendName = metadataFileNameWithExtendName;
      String newFileNameWithExtendName = metadataFileNameWithExtendName =
          vldInfo.getCmpName() + cmpExtendName;
      //需要Lcm提供renameMetadata方法
      metadataService.renameMetadata(oldFileNameWithExtendName, newFileNameWithExtendName, path);
      fullPath = path + UdtUtils.getSeparator() + newFileNameWithExtendName;
    } else {
      metadataFileNameWithExtendName = vldInfo.getCmpName() + cmpExtendName;
      if (!metadataService.isMetadataExist(path, metadataFileNameWithExtendName)) {
        throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_UDT_MODEL_0001, metadataFileNameWithExtendName);
      }
      fullPath = path + UdtUtils.getSeparator() + vldInfo.getCmpName() + cmpExtendName;
    }
    ///#endregion ---------------------------兼容旧版本---------------------------
    GspComponent originalComponent = getOriginalComponent(path, metadataFileNameWithExtendName);
    //2、赋值
    evaluateComponentInfo(component, vldInfo, originalComponent);
    //4、修改更新构件元数据
    GspMetadataExchangeUtil.getInstance()
        .updateGspMetadata(component, fullPath, this.udtDefCode, this.bizObjectID, this.nameSpace);
  }

  protected final String javaModuleImportPackage(String assemblyName) {
    return ComponentGenUtil.prepareJavaPackageName(assemblyName) + ".";
  }

  /**
   * 获得Java模版类的名称
   */
  protected final String javaModuleClassName(String classNamestr, String packageNameStr) {
    String connections = "";
    if (!UdtUtils.checkNull((classNamestr))) {
      String className = classNamestr.substring(classNamestr.lastIndexOf('.'));
      connections = String.format("%1$s%2$s", packageNameStr, className);
    }
    return connections;
  }

  /**
   * 获取修改元数据之前的元数据信息
   */
  private GspComponent getOriginalComponent(String path, String metadataFileNameWithSuffix) {
    MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);
    GspMetadata metadata = metadataService.loadMetadata(metadataFileNameWithSuffix, path);
    //TODO GspComponentMetadata待确认
//		if (metadata.getContent() instanceof GspComponentMetadata)
//		{
//			ComponentSerializer serializer = new ComponentSerializer();
//			Object tempVar = ((IMetadataContentSerializer)((serializer instanceof IMetadataContentSerializer) ? serializer : null)).DeSerialize((JObject)JToken.Parse(((GspComponentMetadata)((metadata.Content instanceof GspComponentMetadata) ? metadata.Content : null)).ContentString));
//			GspComponent originalComponent = (GspComponent)((tempVar instanceof GspComponent) ? tempVar : null);
//			return originalComponent;
//		}
//		else
//		{
    GspComponent originalComponent = (GspComponent) ((metadata.getContent() instanceof GspComponent)
        ? metadata.getContent() : null);
    return originalComponent;
  }
}